{
  "cells": [
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "jWESX0tpdrE-"
      },
      "source": [
        "##### Copyright 2025 Google LLC."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 4,
      "metadata": {
        "cellView": "form",
        "id": "YQvTrJpxzRlJ"
      },
      "outputs": [],
      "source": [
        "#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
        "# you may not use this file except in compliance with the License.\n",
        "# You may obtain a copy of the License at\n",
        "#\n",
        "# https://www.apache.org/licenses/LICENSE-2.0\n",
        "#\n",
        "# Unless required by applicable law or agreed to in writing, software\n",
        "# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
        "# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
        "# See the License for the specific language governing permissions and\n",
        "# limitations under the License."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "3hp_P0cDzTWp"
      },
      "source": [
        "# Gemini - Multimodal live API: Tool use"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "OLW8VU78zZOc"
      },
      "source": [
        "<a target=\"_blank\" href=\"https://colab.research.google.com/github/google-gemini/cookbook/blob/main/quickstarts/Get_started_LiveAPI_tools.ipynb\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" height=30/></a>"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "y7f4kFby0E6j"
      },
      "source": [
        "This notebook provides examples of how to use tools with the multimodal live API with [Gemini 2.5](https://ai.google.dev/gemini-api/docs/models/gemini-v2).\n",
        "\n",
        "The API provides Google Search, Code Execution and Function Calling tools. The earlier Gemini models supported versions of these tools. The biggest change with Gemini 2.5 (in the Live API) is that, basically, all the tools are handled by Code Execution. With that change, you can use **multiple tools** in a single API call, and the model can use multiple tools in a single code execution block.  \n",
        "\n",
        "This tutorial assumes you are familiar with the Live API, as described in the [this tutorial](../quickstarts/Get_started_LiveAPI.ipynb)."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Mfk6YY3G5kqp"
      },
      "source": [
        "## Setup"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "d5027929de8f"
      },
      "source": [
        "### Install SDK\n",
        "\n",
        "The new **[Google Gen AI SDK](https://ai.google.dev/gemini-api/docs/sdks)** provides programmatic access to Gemini 2.5 (and previous models) using both the [Google AI for Developers](https://ai.google.dev/gemini-api/docs) and [Vertex AI](https://cloud.google.com/vertex-ai/generative-ai/docs/overview) APIs. With a few exceptions, code that runs on one platform will run on both. This means that you can prototype an application using the Developer API and then migrate the application to Vertex AI without rewriting your code.\n",
        "\n",
        "More details about this new SDK on the [documentation](https://ai.google.dev/gemini-api/docs/sdks) or in the [Getting started](../quickstarts/Get_started.ipynb) notebook."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 5,
      "metadata": {
        "id": "46zEFO2a9FFd"
      },
      "outputs": [],
      "source": [
        "%pip install -U -q google-genai"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "CTIfnvCn9HvH"
      },
      "source": [
        "### Setup your API key\n",
        "\n",
        "To run the following cell, your API key must be stored it in a Colab Secret named `GOOGLE_API_KEY`. If you don't already have an API key, or you're not sure how to create a Colab Secret, see [Authentication ![image](https://storage.googleapis.com/generativeai-downloads/images/colab_icon16.png)](../quickstarts/Authentication.ipynb) for an example."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 32,
      "metadata": {
        "id": "A1pkoyZb9Jm3"
      },
      "outputs": [],
      "source": [
        "from google.colab import userdata\n",
        "import os\n",
        "\n",
        "os.environ['GOOGLE_API_KEY']=userdata.get('GOOGLE_API_KEY')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Y13XaCvLY136"
      },
      "source": [
        "### Initialize SDK client\n",
        "\n",
        "The client will pickup your API key from the environment variable.\n",
        "To use the live API you need to set the client version to `v1alpha`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 34,
      "metadata": {
        "id": "HghvVpbU0Uap"
      },
      "outputs": [],
      "source": [
        "from google import genai\n",
        "\n",
        "client = genai.Client(http_options={\"api_version\": \"v1alpha\"})"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "QOov6dpG99rY"
      },
      "source": [
        "### Select a model\n",
        "\n",
        "Either select the latest stable model or one of the preview ones. Note that the native audio models like `gemini-2.5-flash-native-audio-preview-09-2025` won't work in this notebook as they only can't output text only which is what colab imposes to us."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 42,
      "metadata": {
        "id": "27Fikag0xSaB"
      },
      "outputs": [],
      "source": [
        "MODEL_ID = 'gemini-live-2.5-flash-preview'  # @param ['gemini-2.0-flash-live-001', 'gemini-live-2.5-flash-preview', 'gemini-2.5-flash-native-audio-preview-09-2025'] {allow-input: true, isTemplate: true}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "pLU9brx6p5YS"
      },
      "source": [
        "### Imports"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 9,
      "metadata": {
        "id": "yMG4iLu5ZLgc"
      },
      "outputs": [],
      "source": [
        "import asyncio\n",
        "import contextlib\n",
        "import json\n",
        "import wave\n",
        "\n",
        "from IPython.display import display, Markdown, Audio, HTML\n",
        "\n",
        "from google import genai\n",
        "from google.genai import types"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "yrb4aX5KqKKX"
      },
      "source": [
        "### Utilities"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rmfQ-NvFI7Ct"
      },
      "source": [
        "You're going to use the Live API's audio output, the easiest way hear it in Colab is to write the `PCM` data out as a `WAV` file:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 10,
      "metadata": {
        "id": "p2aGpzlR-60Q"
      },
      "outputs": [],
      "source": [
        "@contextlib.contextmanager\n",
        "def wave_file(filename, channels=1, rate=24000, sample_width=2):\n",
        "    with wave.open(filename, \"wb\") as wf:\n",
        "        wf.setnchannels(channels)\n",
        "        wf.setsampwidth(sample_width)\n",
        "        wf.setframerate(rate)\n",
        "        yield wf"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "KfdD9mVxqatm"
      },
      "source": [
        "Use a logger so it's easier to switch on/off debugging messages."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 11,
      "metadata": {
        "id": "wgHJgpV9Zw4E"
      },
      "outputs": [],
      "source": [
        "import logging\n",
        "logger = logging.getLogger('Live')\n",
        "logger.setLevel('INFO')\n",
        "#logger.setLevel('DEBUG')  # Switch between \"INFO\" and \"DEBUG\" to toggle debug messages."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "4hiaxgUCZSYJ"
      },
      "source": [
        "## Get started"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "LQoca-W7ri0y"
      },
      "source": [
        "Most of the Live API setup will be similar to the [starter tutorial](../quickstarts/Get_started_LiveAPI.ipynb). Since this tutorial doesn't focus on the realtime interactivity of the API, the code has been simplified: This code uses the Live API, but it only sends a single text prompt, and listens for a single turn of replies.\n",
        "\n",
        "You can set `modality=\"AUDIO\"` on any of the examples to get the spoken version of the output."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 12,
      "metadata": {
        "id": "lwLZrmW5zR_P"
      },
      "outputs": [],
      "source": [
        "n = 0\n",
        "async def run(prompt, modality=\"TEXT\", tools=None):\n",
        "  global n\n",
        "  if tools is None:\n",
        "    tools=[]\n",
        "\n",
        "  config = {\n",
        "          \"tools\": tools,\n",
        "          \"response_modalities\": [modality]\n",
        "  }\n",
        "\n",
        "  async with client.aio.live.connect(model=MODEL_ID, config=config) as session:\n",
        "    display(Markdown(prompt))\n",
        "    display(Markdown('-------------------------------'))\n",
        "    await session.send_client_content(\n",
        "      turns={\"role\": \"user\", \"parts\": [{\"text\": prompt}]}, turn_complete=True\n",
        "    )\n",
        "\n",
        "    audio = False\n",
        "    filename = f'audio_{n}.wav'\n",
        "    with wave_file(filename) as wf:\n",
        "      async for response in session.receive():\n",
        "        logger.debug(str(response))\n",
        "        if response.server_content and response.server_content.model_turn and response.server_content.model_turn.parts and hasattr(response.server_content.model_turn.parts[0], 'text'):\n",
        "          if text := response.server_content.model_turn.parts[0].text:\n",
        "            display(Markdown(text))\n",
        "            continue\n",
        "\n",
        "        if response.server_content and response.server_content.model_turn and response.server_content.model_turn.parts and hasattr(response.server_content.model_turn.parts[0], 'data'):\n",
        "          if data := response.server_content.model_turn.parts[0].data:\n",
        "            print('.', end='')\n",
        "            wf.writeframes(data)\n",
        "            audio = True\n",
        "            continue\n",
        "\n",
        "        server_content = response.server_content\n",
        "        if server_content is not None:\n",
        "          handle_server_content(wf, server_content)\n",
        "          continue\n",
        "\n",
        "        tool_call = response.tool_call\n",
        "        if tool_call is not None:\n",
        "          await handle_tool_call(session, tool_call)\n",
        "\n",
        "\n",
        "  if audio:\n",
        "    display(Audio(filename, autoplay=True))\n",
        "    n = n+1"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ngrvxzrf0ERR"
      },
      "source": [
        "Since this tutorial demonstrates several tools, you'll need more code to handle the different types of objects it returns.\n",
        "\n",
        "- The `code_execution` tool can return `executable_code` and `code_execution_result` parts.\n",
        "- The `google_search` tool may attach a `grounding_metadata` object."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 13,
      "metadata": {
        "id": "CypjqSb-0C-Q"
      },
      "outputs": [],
      "source": [
        "def handle_server_content(wf, server_content):\n",
        "  model_turn = server_content.model_turn\n",
        "  if model_turn:\n",
        "    for part in model_turn.parts:\n",
        "      executable_code = part.executable_code\n",
        "      if executable_code is not None:\n",
        "        display(Markdown('-------------------------------'))\n",
        "        display(Markdown(f'``` python\\n{executable_code.code}\\n```'))\n",
        "        display(Markdown('-------------------------------'))\n",
        "\n",
        "      code_execution_result = part.code_execution_result\n",
        "      if code_execution_result is not None:\n",
        "        display(Markdown('-------------------------------'))\n",
        "        display(Markdown(f'``` \\n{code_execution_result.output}\\n```'))\n",
        "        display(Markdown('-------------------------------'))\n",
        "\n",
        "  grounding_metadata = getattr(server_content, 'grounding_metadata', None)\n",
        "  if grounding_metadata is not None:\n",
        "    display(\n",
        "        HTML(grounding_metadata.search_entry_point.rendered_content))\n",
        "\n",
        "  return"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "dPnXSNZ5rydM"
      },
      "source": [
        "- Finally, with the `function_declarations` tool, the API may return `tool_call` objects. To keep this code minimal, the `tool_call` handler just replies to every function call with a response of `\"ok\"`."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 14,
      "metadata": {
        "id": "EmTKF_DtrY4U"
      },
      "outputs": [],
      "source": [
        "async def handle_tool_call(session, tool_call):\n",
        "  print(\"Tool call:\")\n",
        "  function_responses = []\n",
        "  for fc in tool_call.function_calls:\n",
        "    function_response = types.FunctionResponse(\n",
        "        id=fc.id,\n",
        "        name=fc.name,\n",
        "        response={\"result\": \"ok\"},\n",
        "    )\n",
        "    function_responses.append(function_response)\n",
        "  print('>>> ', function_responses)\n",
        "  await session.send_tool_response(function_responses=function_responses)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "TcNu3zUNsI_p"
      },
      "source": [
        "Try running it for a first time:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 39,
      "metadata": {
        "id": "ss9I0MRdHbP2"
      },
      "outputs": [
        {
          "data": {
            "text/markdown": "Hello?",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "Hi",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " there! How can I help you today?",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "await run(prompt=\"Hello?\", tools=None, modality = \"TEXT\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Z_BFBLLGp-Ye"
      },
      "source": [
        "## Simple function call"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "RMq795G6t2hA"
      },
      "source": [
        "The function calling feature of the API Can handle a wide variety of functions. Support in the SDK is still under construction. So keep this simple just send a minimal function definition: Just the function's name.\n",
        "\n",
        "Note that in the live API function calls are independent of the chat turns. The conversation can continue while a function call is being processed."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 43,
      "metadata": {
        "id": "8Y00qqZZt5L-"
      },
      "outputs": [],
      "source": [
        "turn_on_the_lights = {'name': 'turn_on_the_lights'}\n",
        "turn_off_the_lights = {'name': 'turn_off_the_lights'}"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 44,
      "metadata": {
        "id": "8dCjPmz8nEbv"
      },
      "outputs": [
        {
          "data": {
            "text/markdown": "Turn on the lights",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` python\nprint(default_api.turn_on_the_lights())\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-13831775774418635377',\n",
            "  name='turn_on_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n"
          ]
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` \n{'result': 'ok'}\n\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "Turn",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "ed on the lights.",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "prompt = \"Turn on the lights\"\n",
        "\n",
        "tools = [\n",
        "    {'function_declarations': [turn_on_the_lights, turn_off_the_lights]}\n",
        "]\n",
        "\n",
        "await run(prompt, tools=tools, modality = \"TEXT\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "fmPB49ZodNKr"
      },
      "source": [
        "## Async function calling\n",
        "\n",
        "**Async function calling** lets the model manage its function calls asynchronously and without blocking the user input.\n",
        "\n",
        "You can decide how the model will behave when the function call ends between saying nothing, interrupting what it's doing or waiting to finish its current task.\n",
        "\n",
        "The next cells are going to use a slightly updated code to use the Live API so that the session stays open for 20s and accepts multiple requests that are sent to the model every 10s. Expand the next cell if you are curious about this implementation."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 45,
      "metadata": {
        "cellView": "form",
        "id": "M4TCYuB7XQXn"
      },
      "outputs": [],
      "source": [
        "# @title Live class with multiple messages (just run this cell)\n",
        "\n",
        "import collections.abc\n",
        "import inspect\n",
        "from asyncio.exceptions import CancelledError\n",
        "import traceback\n",
        "\n",
        "class Live:\n",
        "  def __init__(self, client):\n",
        "    self.client = client\n",
        "\n",
        "\n",
        "  async def run(self, config, functions=None, messages=None):\n",
        "    self.config = config\n",
        "    self.send_queue = asyncio.Queue()\n",
        "    self.tool_call_queue = asyncio.Queue()\n",
        "\n",
        "    try:\n",
        "      async with (\n",
        "            client.aio.live.connect(model=MODEL_ID, config=config) as session,\n",
        "            asyncio.TaskGroup() as tg\n",
        "      ):\n",
        "        self.session = session\n",
        "        recv_task = tg.create_task(self._recv())\n",
        "        send_task = tg.create_task(self._send())\n",
        "        tool_call_task = tg.create_task(self._run_tool_calls(functions))\n",
        "        read_text= tg.create_task(self._read_text(messages))\n",
        "\n",
        "\n",
        "        await read_text\n",
        "        await asyncio.sleep(20) # Keeping the socket open for 20s to wait for the FC and different messages\n",
        "\n",
        "        raise CancelledError\n",
        "    except CancelledError:\n",
        "      pass\n",
        "    except ExceptionGroup as EG:\n",
        "      traceback.print_exception(EG)\n",
        "\n",
        "  async def _recv(self):\n",
        "    try:\n",
        "      mode = None\n",
        "      while True:\n",
        "        async for response in self.session.receive():\n",
        "          logger.debug(str(response))\n",
        "          if response.server_content and response.server_content.model_turn and response.server_content.model_turn.parts and hasattr(response.server_content.model_turn.parts[0], 'text'):\n",
        "            if text := response.server_content.model_turn.parts[0].text:\n",
        "              if mode != 'text':\n",
        "                mode = 'text'\n",
        "                print()\n",
        "              print(text)\n",
        "          else:\n",
        "            if mode == 'text':\n",
        "              mode = 'other'\n",
        "              print()\n",
        "            print(f'<<<  {response.model_dump_json(exclude_none=True)}\\n')\n",
        "\n",
        "          tool_call = response.tool_call\n",
        "          if tool_call is not None:\n",
        "            await self.tool_call_queue.put(tool_call)\n",
        "\n",
        "    except asyncio.CancelledError:\n",
        "      pass\n",
        "\n",
        "  async def _send(self):\n",
        "    while True:\n",
        "      msg = await self.send_queue.get()\n",
        "      print(f'>>> {repr(msg)}\\n')\n",
        "      await self.session.send_client_content(turns=msg,turn_complete=True)\n",
        "\n",
        "  async def _run_tool_calls(self, functions):\n",
        "    while True:\n",
        "      tool_call = await self.tool_call_queue.get()\n",
        "      for fc in tool_call.function_calls:\n",
        "        fun = functions[fc.name]\n",
        "        called = fun(**fc.args)\n",
        "        if inspect.iscoroutine(called):\n",
        "          print(f'>> Starting {fc.name}\\n')\n",
        "          result = await called\n",
        "          print(f'>> Done {fc.name} >>> {repr(result)}\\n')\n",
        "          result = self._wrap_function_result(fc, result)\n",
        "          await self.session.send_tool_response(function_responses=[result])\n",
        "        elif isinstance(called, collections.abc.AsyncIterable):\n",
        "          async for result in called:\n",
        "            result.will_continue=True\n",
        "            result = self._wrap_function_result(fc, result)\n",
        "            print(f\">>> {repr(result)}\\n\")\n",
        "            await self.session.send_tool_response(function_responses=[result])\n",
        "\n",
        "          result = self._wrap_function_result(\n",
        "              fc,\n",
        "              types.FunctionResponse(will_continue=False)\n",
        "          )\n",
        "          print(f\">>> {repr(result)}\\n\")\n",
        "          await self.session.send_tool_response(\n",
        "              function_responses=[result]\n",
        "          )\n",
        "\n",
        "\n",
        "        else:\n",
        "          raise TypeError(f\"expected {fc.name} to return a coroutine, or an \"\n",
        "                          f\"AsyncIterable, got {type(fun)}\")\n",
        "\n",
        "  def _wrap_function_result(self, fc, result):\n",
        "    if result is None:\n",
        "      return types.FunctionResponse(\n",
        "          name=fc.name,\n",
        "          id=fc.id,\n",
        "          response={'result': 'ok'}\n",
        "      )\n",
        "    elif isinstance(result, types.FunctionResponse):\n",
        "      result.name = fc.name\n",
        "      result.id = fc.id\n",
        "      return result\n",
        "    else:\n",
        "      return types.FunctionResponse(\n",
        "          name=fc.name,\n",
        "          id=fc.id,\n",
        "          response= {'result': result}\n",
        "      )\n",
        "\n",
        "  async def _read_text(self, messages):\n",
        "    if messages:\n",
        "        for n, message in enumerate(messages):\n",
        "            await self.send_queue.put({\n",
        "                'role': 'user',\n",
        "                'parts': [{'text': message}]\n",
        "            })\n",
        "            if n+1 < len(messages):\n",
        "              await asyncio.sleep(5)\n",
        "    else:\n",
        "        while True:\n",
        "            message = await asyncio.to_thread(input, \"message > \")\n",
        "            if message.lower() == \"q\":\n",
        "                break\n",
        "            await self.send_queue.put({\n",
        "                'role': 'user',\n",
        "                'parts': [{'text': message}]\n",
        "            })"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "GVStsmfrZX9x"
      },
      "source": [
        "### Default behavior: Blocking\n",
        "\n",
        "Let's start with the default behavior. First define a mock weather function that simulates compute time by waiting 10s.\n",
        "\n",
        "The default behavior functions as a FIFO queue: the function call is added to a queue, and any subsequent requests are queued (blocked) behind it until it finishes processing."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 46,
      "metadata": {
        "id": "DSp2PU0MbfBR"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> {'role': 'user', 'parts': [{'text': \"What's the weather in Vegas?\"}]}\n",
            "\n",
            "<<<  {\"tool_call\":{\"function_calls\":[{\"id\":\"function-call-395220346347865271\",\"args\":{},\"name\":\"get_weather_vegas\"}]}}\n",
            "\n",
            ">> Starting get_weather_vegas\n",
            "\n",
            ">>> {'role': 'user', 'parts': [{'text': 'In the meantime tell me about the Paris casino'}]}\n",
            "\n",
            ">> Done get_weather_vegas >>> {'weather': 'Sunny, 42 degrees'}\n",
            "\n",
            "\n",
            "The weather in Vegas\n",
            " is Sunny, 42 degrees.\n",
            "\n",
            "<<<  {\"server_content\":{\"generation_complete\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":229,\"response_token_count\":25,\"total_token_count\":254,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":229}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":25}]}}\n",
            "\n",
            "\n",
            "I\n",
            " can tell you that the Paris Las Vegas Casino is a beautiful hotel and casino on\n",
            " the Las Vegas Strip in Paradise, Nevada. It is owned and operated by Caesars Entertainment and has a 540-foot-tall replica of the Eiffel Tower, a two-thirds-size Arc de Triomphe, a balloon\n",
            " sign, and other well-known Parisian landmarks. The Paris Las Vegas has 2,916 rooms and a 95,263 square-foot casino with over 1,700 slot machines and 85\n",
            " game tables.\n",
            "\n",
            "\n",
            "<<<  {\"server_content\":{\"generation_complete\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":260,\"response_token_count\":118,\"total_token_count\":378,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":260}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":118}]}}\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Mock function, takes 10s to process\n",
        "async def get_weather_vegas():\n",
        "  await asyncio.sleep(10)\n",
        "  return {'weather': \"Sunny, 42 degrees\"}\n",
        "\n",
        "# multiple prompts, they are going to be asked with 5s delay between each of them.\n",
        "questions = [\n",
        "    \"What's the weather in Vegas?\",\n",
        "    \"In the meantime tell me about the Paris casino\"\n",
        "]\n",
        "\n",
        "await Live(client).run(\n",
        "    messages=questions,\n",
        "    functions={\n",
        "        'get_weather_vegas': get_weather_vegas,\n",
        "    },\n",
        "    config={\n",
        "        \"response_modalities\": [\"TEXT\"],\n",
        "        \"tools\": [\n",
        "            {\n",
        "                'function_declarations': [\n",
        "                    {'name': 'get_weather_vegas',  \"behavior\": \"UNSPECIFIED\"}, # This is default behavior, equivalent to BLOCKING\n",
        "                ]\n",
        "            }\n",
        "        ]\n",
        "    }\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "siPiuJ8LW0BC"
      },
      "source": [
        "As you can see, the model called the `get_weather_vegas` function right away, but then the second question was ignored as the model was still waiting for the function call results. It only started to answer the second question after answering the function call."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "tI2LZVgHXNLB"
      },
      "source": [
        "### **Interrupt**: stop what you're doing and handle this result\n",
        "\n",
        "This time, `behavior` is set as `NON_BLOCKING`, which means it will use async function calling.\n",
        "\n",
        "When you do, you need to define what the model will do when it will get the result of the function call. This is managed inside of the function, or within your script that handles the funcion calls (since Automatic function calling is not available) by adding a `scheduling` value in the `FunctionResponse`.\n",
        "\n",
        "This time the `scheduling` behavior is \"**`Interrupt`**\", which means that as soon as it gets a response, the model will stop what it's saying and process the response right away."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 47,
      "metadata": {
        "id": "e7-Sq7VpXNLC"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> {'role': 'user', 'parts': [{'text': \"What's the weather in Vegas?\"}]}\n",
            "\n",
            "<<<  {\"tool_call\":{\"function_calls\":[{\"id\":\"function-call-2548436875001823064\",\"args\":{},\"name\":\"get_weather_vegas\"}]}}\n",
            "\n",
            ">> Starting get_weather_vegas\n",
            "\n",
            "\n",
            "It\n",
            " is running. I will respond to you once I have the results.\n",
            "\n",
            "<<<  {\"server_content\":{\"generation_complete\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":511,\"response_token_count\":28,\"total_token_count\":539,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":511}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":28}]}}\n",
            "\n",
            ">>> {'role': 'user', 'parts': [{'text': \"In the meantime tell me what you know about the Paris casino and all there's to do and see in it. Then continue to tell me about the Vegas casinos until I tell you to stom talking. Don't ask me, just talk non-stopThen can you tell me what's your favorite cirque du soleil show?\"}]}\n",
            "\n",
            "\n",
            "While\n",
            " I wait for the weather update, let me tell you about the Paris Las Vegas Hotel\n",
            " & Casino! It's a fantastic spot that really brings the romance and charm of the City of Lights to the desert.\n",
            "\n",
            "Of course, the most iconic feature is the Eiffel Tower viewing deck. You can take an elevator up 4\n",
            "6 stories for breathtaking 360-degree views of the Las Vegas Strip, especially beautiful at night. They also have a wonderful Eiffel Tower Restaurant up there if you're looking for a special dining experience with a view. And don't forget\n",
            " the Arc de Triomphe and the replica of the Louvre facade, perfect for photo opportunities!\n",
            "\n",
            "Inside, the casino floor has a distinctly Parisian feel, with cobblestone walkways and street lamps. Beyond the gambling, there are a ton of dining options.\n",
            " You can find everything from casual French bakeries like Le Village Buffet, which is designed to feel like a French village with five different stations, to more upscale options. Gordon Ramsay Steak is a popular choice for a fine dining experience. For something more casual,\n",
            " Mon Ami Gabi is a classic bistro with outdoor seating right on the Strip, perfect for people-watching.\n",
            "\n",
            "The resort also boasts a two-acre pool area called the Pool à Paris, set in a French garden theme directly under the Eiffel Tower.\n",
            " They have various shops, and for entertainment, they often host different shows and performers. The \"Voie de Paris\" is a charming area that mimics a Parisian street with shops and restaurants.\n",
            "\n",
            "Beyond Paris, the Las Vegas Strip is a treasure\n",
            " trove of incredible casinos, each with its own unique theme and attractions.\n",
            "\n",
            "Right next door to Paris is **Bellagio**, famous for its stunning Fountains of Bellagio show. These choreographed water shows set to music are absolutely mesmerizing and happen frequently throughout\n",
            " the day and evening. Inside, the Bellagio Conservatory & Botanical Garden is a must-see, with its elaborate seasonal floral displays that change throughout the year. The Chihuly glass sculpture in the lobby is also a masterpiece. Bellagio also\n",
            " houses upscale shopping, fantastic restaurants, and the \"O\" by Cirque du Soleil show.\n",
            "\n",
            "Then there's **Caesars Palace**, a truly iconic Roman-themed resort. You'll feel like you've stepped into ancient Rome\n",
            " with its grand statues, fountains, and impressive architecture. The Forum Shops at Caesars are an experience in themselves, designed to look like a Roman marketplace with a painted sky that changes from dawn to dusk. They have high-end stores and great\n",
            " restaurants. Caesars also has the Colosseum, a major entertainment venue that hosts top-tier performers and residencies.\n",
            "\n",
            "Further down the Strip, you'll find **The Venetian Resort**, which perfectly recreates the romance of Venice, Italy.\n",
            " You can even take a gondola ride, complete with a serenading gondolier, either outdoors along the Strip or indoors under a painted sky. St. Mark's Square is another beautiful replica, often featuring live performances. The Venetian\n",
            " and its sister property, The Palazzo, offer an incredible array of dining options, from celebrity chef restaurants to more casual fare. They also have the Grand Canal Shoppes, another fantastic indoor shopping experience.\n",
            "\n",
            "**The Wynn and Encore** resorts\n",
            " are known for their luxurious, sophisticated atmosphere and beautiful design. They have stunning floral displays, high-end boutiques, and exquisite dining. The Lake of Dreams show at the Wynn is a unique spectacle of light, water, and puppetry. Both\n",
            " resorts have very elegant pool areas and vibrant nightlife.\n",
            "\n",
            "**MGM Grand** is one of the largest hotels in the world, with an emerald-green theme. It's a massive entertainment complex with a huge casino, multiple theaters for\n",
            ">> Done get_weather_vegas >>> FunctionResponse(\n",
            "  response={\n",
            "    'weather': 'Sunny, 42 degrees'\n",
            "  },\n",
            "  scheduling=<FunctionResponseScheduling.INTERRUPT: 'INTERRUPT'>\n",
            ")\n",
            "\n",
            " shows and concerts, a large variety of restaurants, and a fantastic pool complex known as the Grand Pool Complex. They also house Hakkasan Nightclub, a very popular spot.\n",
            "\n",
            "**New York-New York Hotel & Casino** is easily\n",
            "\n",
            "<<<  {\"server_content\":{\"interrupted\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":604,\"response_token_count\":806,\"total_token_count\":1410,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":604}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":806}]}}\n",
            "\n",
            "\n",
            "Okay\n",
            ", I have the weather update for you! It's sunny and 42 degrees in\n",
            " Vegas.\n",
            "\n",
            "Continuing on with the Vegas casinos and their attractions!\n",
            "\n",
            "As I was saying, **New York-New York Hotel & Casino** is easily recognizable by its Manhattan skyline facade, complete with a replica Statue of Liberty and Brooklyn Bridge. The\n",
            " main attraction here is undoubtedly The Big Apple Coaster, which weaves in and out of the hotel's towers, offering thrilling drops and inversions. Inside, you'll find areas themed like Greenwich Village and Times Square, with various casual\n",
            " dining options and bars, including the lively dueling piano bar, Bar at Times Square.\n",
            "\n",
            "**Excalibur Hotel & Casino** is a fun, family-friendly option with a medieval castle theme. It's quite distinctive with its colorful\n",
            " turrets. They have a dinner show called Tournament of Kings, where knights joust and perform acrobatics while you eat. There's also a large arcade and various casual restaurants.\n",
            "\n",
            "**Luxor Hotel and Casino** is hard to miss with its\n",
            " striking pyramid shape and the powerful Sky Beam shooting up into the night sky. Inside, you'll find an inclinators that travel up the sides of the pyramid. The hotel has various attractions, including the \"Bodies... The Exhibition\" and \"\n",
            "Titanic: The Artifact Exhibition.\" They also have a large pool complex and an assortment of dining and entertainment options.\n",
            "\n",
            "**Mandalay Bay Resort and Casino** is at the far south end of the Strip and is known for its incredible Mandal\n",
            "ay Bay Beach. This 11-acre aquatic playground features a wave pool, a lazy river, and real sand beaches. It's a fantastic spot to relax and soak up the sun. The resort also houses the Shark Reef Aquarium\n",
            ", a large aquarium with various sharks, exotic fish, and reptiles. Mandalay Bay also has a wide range of restaurants, bars, and the House of Blues music venue.\n",
            "\n",
            "**Planet Hollywood Resort & Casino** has a more modern,\n",
            " trendy vibe, often associated with Hollywood glamour. It's located right in the heart of the Strip. The Miracle Mile Shops, an enclosed shopping mall with over 170 stores and restaurants, wraps around the casino floor. Planet Hollywood also hosts\n",
            " various residencies and shows in its Zappos Theater.\n",
            "\n",
            "**The LINQ Hotel + Experience** is a very vibrant and energetic resort, particularly known for the LINQ Promenade. This open-air entertainment district leads to the High Roller, which\n",
            " is the world's tallest observation wheel, offering incredible panoramic views of the city. The Promenade itself is bustling with shops, restaurants, bars, and entertainment venues, including the Brooklyn Bowl.\n",
            "\n",
            "**Flamingo Las Vegas Hotel & Casino** is one\n",
            " of the Strip's original resorts and still maintains a classic Vegas charm with its vibrant pink theme. It's home to a beautiful wildlife habitat where you can see real flamingos, as well as other birds and fish, in a lush\n",
            " garden setting. The pool area, known as the GO Pool, is a lively party spot.\n",
            "\n",
            "**Circus Circus Hotel, Casino & Theme Park** is another family-friendly option, particularly known for its Adventuredome, a large\n",
            " indoor amusement park with roller coasters and other rides. They also offer free circus acts on the Midway Stage, making it a unique and entertaining spot for all ages.\n",
            "\n",
            "And that's just scratching the surface of the incredible casino experiences in Las Vegas\n",
            "! Each one offers a distinct atmosphere, from ancient Rome to modern luxury, and provides endless opportunities for entertainment, dining, and relaxation.\n",
            "\n",
            "Now, regarding your question about my favorite Cirque du Soleil show – that's a tough one, as\n",
            " they are all incredibly creative and spectacular in their own ways! If I had to pick just one, I would lean towards **\"O\" by Cirque du Soleil** at the Bellagio.\n",
            "\n",
            "What makes \"O\" so extraordinary is its unique\n",
            " aquatic stage. The entire performance takes place in, on, and above a 1.5-million-gallon pool of water. Performers appear and disappear from the water, creating truly magical and seamless transitions between aerial acts, synchronized swimming, and diving\n",
            ". The way they integrate the water element into every aspect of the show, from the set design to the acrobatics, is simply breathtaking. The artistry, the stunning costumes, the live music, and the sheer skill of the performers are all top\n",
            "-notch. It truly feels like you're entering a dream world. The scale and ambition of \"O\" are unparalleled, and it leaves a lasting impression.\n",
            "\n",
            "While all Cirque du Soleil shows are amazing, \"O\" stands\n",
            " out for its innovative use of water and its ability to transport the audience to another dimension.\n",
            "\n",
            "<<<  {\"server_content\":{\"generation_complete\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":1480,\"response_token_count\":971,\"total_token_count\":2451,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":1480}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":971}]}}\n",
            "\n"
          ]
        }
      ],
      "source": [
        "# Mock function, takes 10s to process\n",
        "async def get_weather_vegas():\n",
        "  await asyncio.sleep(10)\n",
        "  return types.FunctionResponse(\n",
        "      response={'weather': \"Sunny, 42 degrees\"},\n",
        "      scheduling=\"INTERRUPT\"\n",
        "  )\n",
        "\n",
        "# multiple prompts, they are going to be asked with 5s delay between each of them.\n",
        "questions = [\n",
        "    \"What's the weather in Vegas?\",\n",
        "    \"In the meantime tell me what you know about the Paris casino and all there's to do and see in it. Then continue to tell me about the Vegas casinos until I tell you to stom talking. Don't ask me, just talk non-stop\"\n",
        "    \"Then can you tell me what's your favorite cirque du soleil show?\"\n",
        "]\n",
        "\n",
        "await Live(client).run(\n",
        "    messages=questions,\n",
        "    functions={\n",
        "        'get_weather_vegas': get_weather_vegas,\n",
        "    },\n",
        "    config={\n",
        "        \"response_modalities\": [\"TEXT\"],\n",
        "        \"tools\": [\n",
        "            {\n",
        "                'function_declarations': [\n",
        "                    {'name': 'get_weather_vegas',  \"behavior\": \"NON_BLOCKING\"},\n",
        "                ]\n",
        "            }\n",
        "        ]\n",
        "    }\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "YObbWmcW24sH"
      },
      "source": [
        "As you can see, this time, the model acknowledged our request by saying something like \"`The weather in Vegas request is running. I'll let you know when it's done`\", then continues to process what you asked it, and then when the function response comes back, it stopped what it was doing, told us about the weather, and then continued to talk about what it was talking about."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "rLbBme4MTBy7"
      },
      "source": [
        "### **Wait until Idle**: Finish what you're doing before handling this result\n",
        "\n",
        "Once again, the `behavior` is set as `NON_BLOCKING`, which means it will use async function calling and you will have to add a `scheduling` value in the `FunctionResponse`.\n",
        "\n",
        "This time the `scheduling` behavior is \"**`When_idle`**\", which means that the model will **wait until it's finished** with what it's saying and only then tell us about what you asked for."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 48,
      "metadata": {
        "id": "bhMQLAVqTBy8"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> {'role': 'user', 'parts': [{'text': \"What's the weather in Vegas?\"}]}\n",
            "\n",
            "<<<  {\"tool_call\":{\"function_calls\":[{\"id\":\"function-call-14628508452628440626\",\"args\":{},\"name\":\"get_weather_vegas\"}]}}\n",
            "\n",
            ">> Starting get_weather_vegas\n",
            "\n",
            "\n",
            "Got\n",
            " it. I'm fetching the weather in Vegas.\n",
            "\n",
            "<<<  {\"server_content\":{\"generation_complete\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":512,\"response_token_count\":25,\"total_token_count\":537,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":512}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":25}]}}\n",
            "\n",
            ">>> {'role': 'user', 'parts': [{'text': \"In the meantime, without using tools, tell me what you know about the Paris casino and all there's to do and see in it. Tell me about each casino on the strip!\"}]}\n",
            "\n",
            "\n",
            "The\n",
            " Paris Las Vegas Hotel & Casino is a well-known themed resort on the Las Vegas\n",
            " Strip, recognizable by its half-scale replica of the Eiffel Tower and other Parisian landmarks.\n",
            "\n",
            "Here's a glimpse of what you can expect:\n",
            "\n",
            "**The Casino:** As with most Vegas resorts, the Paris casino offers a wide array\n",
            " of gaming options, including slot machines, video poker, and various table games like blackjack, roulette, craps, and baccarat.\n",
            "\n",
            "**Dining:** Paris Las Vegas boasts a diverse culinary scene, ranging from casual cafes to upscale dining experiences\n",
            ">> Done get_weather_vegas >>> FunctionResponse(\n",
            "  response={\n",
            "    'weather': 'Sunny, 42 degres'\n",
            "  },\n",
            "  scheduling=<FunctionResponseScheduling.WHEN_IDLE: 'WHEN_IDLE'>\n",
            ")\n",
            "\n",
            ". Some notable options include:\n",
            "*   **Eiffel Tower Restaurant:** Located within the Eiffel Tower replica, this restaurant offers upscale French cuisine with panoramic views of the Strip and the Bellagio Fountains.\n",
            "*   **Gordon Ramsay Steak:**\n",
            " A high-end steakhouse by the celebrity chef.\n",
            "*   **Mon Ami Gabi:** A popular bistro with outdoor seating overlooking the Strip, serving French classics.\n",
            "*   **Le Village Buffet:** A buffet designed to resemble a French\n",
            " village, offering various food stations.\n",
            "\n",
            "**Entertainment & Attractions:**\n",
            "*   **Eiffel Tower Viewing Deck:** You can take an elevator to the top of the Eiffel Tower replica for stunning 360-degree views of Las Vegas.\n",
            "*\n",
            "   **\"Ooh La La\" — The Show:** (Note: Shows can change frequently, so it's always good to check current listings). Paris often hosts various live entertainment, includingيه production shows, concerts, and residencies.\n",
            "*\n",
            "   **The Spa by Mandara:** A full-service spa offering treatments and relaxation.\n",
            "*   **Shopping:** There are several boutiques and shops within the resort.\n",
            "\n",
            "**Nightlife:**\n",
            "*   **Chateau Nightclub &\n",
            " Rooftop:** A multi-level nightclub offering indoor and outdoor experiences with views of the Strip.\n",
            "*   Various bars and lounges throughout the casino.\n",
            "\n",
            "**Other Casinos on the Strip (without using tools, this is a broad overview):**\n",
            "\n",
            "The\n",
            " Las Vegas Strip is a roughly 4.2-mile stretch of Las Vegas Boulevard known for its concentration of world-class resorts, casinos, and attractions. Each resort typically has its own theme and unique offerings:\n",
            "\n",
            "*   **Bell\n",
            "agio:** Known for its iconic Fountains of Bellagio, a conservatory, and upscale atmosphere.\n",
            "*   **Caesars Palace:** A Roman-themed resort with a large casino, Colosseum entertainment venue, and Forum Shops.\n",
            "*\n",
            "   **MGM Grand:** One of the largest hotels in the world, featuring a massive casino, arena, and numerous dining and entertainment options.\n",
            "*   **Aria:** A more modern and luxurious resort within the CityCenter complex, known for\n",
            " its contemporary design and high-tech amenities.\n",
            "*   **Cosmopolitan:** A stylish and trendy resort popular with a younger crowd, featuring unique dining, nightlife, and balconies in many rooms.\n",
            "*   **Wynn and Encore\n",
            ":** Sister resorts known for their elegance, luxurious accommodations, fine dining, and elaborate landscaping.\n",
            "*   **Venetian and Palazzo:** Italian-themed resorts with gondola rides, Grand Canal Shoppes, and extensive convention facilities.\n",
            "*   \n",
            "**Mirage:** Polynesian-themed, famous for its volcanic eruption show and Siegfried & Roy's Secret Garden and Dolphin Habitat.\n",
            "*   **Treasure Island (TI):** Caribbean-themed, previously known for its siren show.\n",
            "*\n",
            "   **Flamingo:** One of the older and more historic resorts, known for its pink facade and wildlife habitat.\n",
            "*   **Harrah's:** Centrally located with a lively, carnival-like atmosphere.\n",
            "*   **LIN\n",
            "Q Hotel + Experience:** Modern and vibrant, home to the High Roller observation wheel and LINQ Promenade.\n",
            "*   **Planet Hollywood:** Hollywood-themed, with a Miracle Mile Shops and a theater that hosts residencies.\n",
            "*   **New\n",
            " York-New York:** Replicates the New York City skyline, complete with a roller coaster.\n",
            "*   **Luxor:** Pyramid-shaped resort with an Egyptian theme, featuring a beam of light into the sky.\n",
            "*   **M\n",
            "andalay Bay:** South Pacific-themed, with a large convention center, Shark Reef Aquarium, and a beach/wave pool complex.\n",
            "*   **Excalibur:** Medieval castle-themed, popular with families.\n",
            "*   **Circ\n",
            "us Circus:** Circus-themed, geared towards families, with an indoor Adventuredome theme park.\n",
            "*   **Resorts World:** One of the newer resorts, with a modern Asian theme and a diverse range of dining and entertainment.\n",
            "*   \n",
            "**Sahara:** A historic name on the Strip, recently renovated and rebranded.\n",
            "*   **Strat (formerly Stratosphere):** Known for its observation tower with thrill rides at the top.\n",
            "\n",
            "This is by no means an exhaustive list, as\n",
            " the Strip is constantly evolving with new developments and changes!\n",
            "\n",
            "<<<  {\"server_content\":{\"generation_complete\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":572,\"response_token_count\":1015,\"total_token_count\":1587,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":572}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":1015}]}}\n",
            "\n",
            "\n",
            "The\n",
            " weather in Vegas is sunny and 42 degrees.\n",
            "\n",
            "<<<  {\"server_content\":{\"generation_complete\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":1659,\"response_token_count\":12,\"total_token_count\":1671,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":1659}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":12}]}}\n",
            "\n"
          ]
        }
      ],
      "source": [
        "import time\n",
        "\n",
        "# Mock function, takes 6s to process\n",
        "async def get_weather_vegas():\n",
        "  await asyncio.sleep(6)\n",
        "  return types.FunctionResponse(\n",
        "      response={'weather': \"Sunny, 42 degres\"},\n",
        "      scheduling=\"WHEN_IDLE\"\n",
        "  )\n",
        "\n",
        "# multiple prompts, they are going to be asked with 5s delay between each of them.\n",
        "questions = [\n",
        "    \"What's the weather in Vegas?\",\n",
        "    \"In the meantime, without using tools, tell me what you know about the Paris casino and all there's to do and see in it. Tell me about each casino on the strip!\"\n",
        "]\n",
        "\n",
        "await Live(client).run(\n",
        "    messages=questions,\n",
        "    functions={\n",
        "        'get_weather_vegas': get_weather_vegas,\n",
        "    },\n",
        "    config={\n",
        "        \"response_modalities\": [\"TEXT\"],\n",
        "        \"tools\": [\n",
        "            {\n",
        "                'function_declarations': [\n",
        "                    {'name': 'get_weather_vegas',  \"behavior\": \"NON_BLOCKING\"},\n",
        "                ]\n",
        "            }\n",
        "        ]\n",
        "    }\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "6xXyeaTR_VpM"
      },
      "source": [
        "As you can see, this time, even though it received the function call response while it was answering about the casinos (cf. `>> Done get_weather_vegas >>> [...] response={'weather': 'Sunny, 42 degres'})` line), it waited until it was finished with its current answer before telling about the weather."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "wMRlAIkeTq1E"
      },
      "source": [
        "### Silent: Just keep what you learned for yourself\n",
        "\n",
        "This time again, the `behavior` is set as `NON_BLOCKING`, which means it will use async function calling and will need a `scheduling` value in the `FunctionResponse`.\n",
        "\n",
        "This time the `scheduling` behavior is \"**`Silent`**\", which means that the model won't tell you when the function call is finished but it might still use that knowledge later on in the conversation."
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 49,
      "metadata": {
        "id": "Cf36tYwITq1F"
      },
      "outputs": [
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            ">>> {'role': 'user', 'parts': [{'text': \"What's the weather in Vegas?\"}]}\n",
            "\n",
            "<<<  {\"tool_call\":{\"function_calls\":[{\"id\":\"function-call-8706718868914709736\",\"args\":{},\"name\":\"get_weather_vegas\"}]}}\n",
            "\n",
            ">> Starting get_weather_vegas\n",
            "\n",
            ">> Done get_weather_vegas >>> FunctionResponse(\n",
            "  response={\n",
            "    'weather': 'Sunny, 42 degres'\n",
            "  },\n",
            "  scheduling=<FunctionResponseScheduling.SILENT: 'SILENT'>\n",
            ")\n",
            "\n",
            "\n",
            "I\n",
            " am fetching the weather information for Las Vegas. Please wait a moment.\n",
            "\n",
            "<<<  {\"server_content\":{\"generation_complete\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":511,\"response_token_count\":28,\"total_token_count\":539,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":511}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":28}]}}\n",
            "\n",
            ">>> {'role': 'user', 'parts': [{'text': 'In the meantime tell me about the Paris casino.'}]}\n",
            "\n",
            "\n",
            "The\n",
            " Paris Las Vegas Casino is a French-themed hotel and casino located on the Las Vegas\n",
            " Strip. It is owned and operated by Caesars Entertainment. The resort features a replica Eiffel Tower, a two-thirds scale Arc de Triomphe, and other Parisian landmarks. The casino floor offers a variety of slot machines, table games, and a\n",
            " race and sports book. \n",
            "\n",
            "\n",
            "<<<  {\"server_content\":{\"generation_complete\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":606,\"response_token_count\":75,\"total_token_count\":681,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":606}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":75}]}}\n",
            "\n",
            ">>> {'role': 'user', 'parts': [{'text': 'Is the temperature over 40 degres?'}]}\n",
            "\n",
            "\n",
            "Yes, the temperature\n",
            " in Las Vegas is 42 degrees, so it is over 40 degrees.\n",
            "\n",
            "<<<  {\"server_content\":{\"generation_complete\":true}}\n",
            "\n",
            "<<<  {\"server_content\":{\"turn_complete\":true},\"usage_metadata\":{\"prompt_token_count\":701,\"response_token_count\":22,\"total_token_count\":723,\"prompt_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":701}],\"response_tokens_details\":[{\"modality\":\"TEXT\",\"token_count\":22}]}}\n",
            "\n"
          ]
        }
      ],
      "source": [
        "import time\n",
        "\n",
        "# Mock function, takes 5s to process\n",
        "async def get_weather_vegas():\n",
        "  time.sleep(10)\n",
        "  return types.FunctionResponse(\n",
        "      response={'weather': \"Sunny, 42 degres\"},\n",
        "      scheduling=\"SILENT\"\n",
        "  )\n",
        "\n",
        "# multiple prompts, they are going to be asked with 5s delay between each of them.\n",
        "questions = [\n",
        "    \"What's the weather in Vegas?\",\n",
        "    \"In the meantime tell me about the Paris casino.\",\n",
        "    \"Is the temperature over 40 degres?\"\n",
        "]\n",
        "\n",
        "await Live(client).run(\n",
        "    messages=questions,\n",
        "    functions={\n",
        "        'get_weather_vegas': get_weather_vegas,\n",
        "    },\n",
        "    config={\n",
        "        \"response_modalities\": [\"TEXT\"],\n",
        "        \"tools\": [\n",
        "            {\n",
        "                'function_declarations': [\n",
        "                    {'name': 'get_weather_vegas',  \"behavior\": \"NON_BLOCKING\"},\n",
        "                ]\n",
        "            }\n",
        "        ]\n",
        "    }\n",
        ")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "25R0uj7F_KB0"
      },
      "source": [
        "This time, as you can see, the model did nothing when the function call ended, but when asked again about the same thing it answered without doing a new function call."
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "eCnCiTbhqE8q"
      },
      "source": [
        "## Code execution"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "P4ptRBNY4N8Q"
      },
      "source": [
        "The `code_execution` lets the model write and run python code. Try it on a math problem the model can't solve from memory:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 50,
      "metadata": {
        "id": "k4dURhC-QoSw"
      },
      "outputs": [
        {
          "data": {
            "text/markdown": "Can you compute the largest prime palindrome under 100000.",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` python\nimport math\n\ndef is_prime(n):\n    if n < 2:\n        return False\n    for i in range(2, int(math.sqrt(n)) + 1):\n        if n % i == 0:\n            return False\n    return True\n\ndef is_palindrome(n):\n    return str(n) == str(n)[::-1]\n\nlargest_prime_palindrome = 0\nfor i in range(99999, 1, -1):\n    if is_palindrome(i):\n        if is_prime(i):\n            largest_prime_palindrome = i\n            break\n\nprint(f\"The largest prime palindrome under 100000 is: {largest_prime_palindrome}\")\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` \nThe largest prime palindrome under 100000 is: 98689\n\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "The largest prime palindrome",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " under 100000 is 98689.",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "\n\nTo arrive at this answer, I first defined two helper functions:\n1. `is_prime(n)`: This function checks if a given number `n` is prime. It iterates from 2 up to the square root",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " of `n` to find any divisors. If it finds any, the number is not prime.\n2. `is_palindrome(n)`: This function checks if a given number `n` is a palindrome by converting it to a",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " string and comparing it to its reverse.\n\nThen, I iterated downwards from 99999 to 1. For each number, I first checked if it was a palindrome using `is_palindrome()`. If it was, I then checked",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " if it was prime using `is_prime()`. The first number that satisfied both conditions (i.e., was both a palindrome and a prime) was the largest prime palindrome, and I stored it and broke out of the loop.",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "prompt=\"Can you compute the largest prime palindrome under 100000.\"\n",
        "\n",
        "tools = [\n",
        "    {'code_execution': {}}\n",
        "]\n",
        "\n",
        "await run(prompt, tools=tools, modality=\"TEXT\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "ueeerkpX5F-v"
      },
      "source": [
        "## Compositional Function Calling\n",
        "\n",
        "Compositional function calling refers to the ability to combine user defined functions with the `code_execution` tool. The model will write them into larger blocks of code, and then pause execution while it waits for you to send back responses for each call.\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 51,
      "metadata": {
        "id": "XzKyL_Rq5sG3"
      },
      "outputs": [
        {
          "data": {
            "text/markdown": "Can write some code to loop through and print integers from 1-20, and every time you hit a multiple of 3 turn on the lights, and every time you hit a multiple of 5 turn them off?",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` python\nfor i in range(1, 21):\n    print(i)\n    if i % 3 == 0:\n        print(default_api.turn_on_the_lights())\n    if i % 5 == 0:\n        print(default_api.turn_off_the_lights())\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-8693960676568926465',\n",
            "  name='turn_on_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n",
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-2896989999026578611',\n",
            "  name='turn_off_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n",
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-17506045652495007545',\n",
            "  name='turn_on_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n",
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-2896989999026580848',\n",
            "  name='turn_on_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n",
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-15646572821636635221',\n",
            "  name='turn_off_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n",
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-333382899261157431',\n",
            "  name='turn_on_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n",
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-333382899261160780',\n",
            "  name='turn_on_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n",
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-9356205211894947117',\n",
            "  name='turn_off_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n",
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-9356205211894947362',\n",
            "  name='turn_on_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n",
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-17785461558308887713',\n",
            "  name='turn_off_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n"
          ]
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` \n1\n2\n3\n{'result': 'ok'}\n4\n5\n{'result': 'ok'}\n6\n{'result': 'ok'}\n7\n8\n9\n{'result': 'ok'}\n10\n{'result': 'ok'}\n11\n12\n{'result': 'ok'}\n13\n14\n15\n{'result': 'ok'}\n{'result': 'ok'}\n16\n17\n18\n{'result': 'ok'}\n19\n20\n{'result': 'ok'}\n\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "The",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " code successfully looped through numbers 1 to 20. It turned on the lights for",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " multiples of 3 and turned off the lights for multiples of 5, printing the corresponding API call result for each action.",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "prompt=\"Can write some code to loop through and print integers from 1-20, and every time you hit a multiple of 3 turn on the lights, and every time you hit a multiple of 5 turn them off?\"\n",
        "\n",
        "tools = [\n",
        "    {'code_execution': {}},\n",
        "    {'function_declarations': [turn_on_the_lights, turn_off_the_lights]}\n",
        "]\n",
        "\n",
        "await run(prompt, tools=tools, modality=\"TEXT\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "G78sxDEcqHyO"
      },
      "source": [
        "## Google search"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "FW10vRPN6UNp"
      },
      "source": [
        "The `google_search` tool lets the model conduct google searches. For example, try asking it about events that are too recent to be in the training data.\n",
        "\n",
        "The search will still execute in `AUDIO` mode, but you won't see the detailed results:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 52,
      "metadata": {
        "id": "QKvWzROJic60"
      },
      "outputs": [
        {
          "data": {
            "text/markdown": "When the latest Brazil vs. Argentina soccer match happened and what was the final score?",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` python\nprint(google_search.search(queries=[\"latest Brazil vs. Argentina soccer match date and score\", \"Brazil vs Argentina last match result\"]))\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` \nLooking up information on Google Search.\n\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "The latest soccer match",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " between Brazil and Argentina took place on **March 25, 20",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "25**, as part of the FIFA World Cup qualifiers. Argentina defeated Brazil with a final score of **4-1** at the Mâs Monumental stadium in Buenos Aires [1, 3, 4, 7,",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " 9]. The goals for Argentina were scored by Julian Alvarez, Enzo Fernández, Alexis Mac Allister, and Giuliano Simeone [7, 9]. Matheus Cunha scored for Brazil [9].\n\nAnother recent match occurred on **November ",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "21, 2023**, where Argentina beat Brazil 1-0 in a 2026 World Cup qualifier [5]. The lone goal was scored by Nicolás Otamendi [5].",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "<style>\n",
              ".container {\n",
              "  align-items: center;\n",
              "  border-radius: 8px;\n",
              "  display: flex;\n",
              "  font-family: Google Sans, Roboto, sans-serif;\n",
              "  font-size: 14px;\n",
              "  line-height: 20px;\n",
              "  padding: 8px 12px;\n",
              "}\n",
              ".chip {\n",
              "  display: inline-block;\n",
              "  border: solid 1px;\n",
              "  border-radius: 16px;\n",
              "  min-width: 14px;\n",
              "  padding: 5px 16px;\n",
              "  text-align: center;\n",
              "  user-select: none;\n",
              "  margin: 0 8px;\n",
              "  -webkit-tap-highlight-color: transparent;\n",
              "}\n",
              ".carousel {\n",
              "  overflow: auto;\n",
              "  scrollbar-width: none;\n",
              "  white-space: nowrap;\n",
              "  margin-right: -12px;\n",
              "}\n",
              ".headline {\n",
              "  display: flex;\n",
              "  margin-right: 4px;\n",
              "}\n",
              ".gradient-container {\n",
              "  position: relative;\n",
              "}\n",
              ".gradient {\n",
              "  position: absolute;\n",
              "  transform: translate(3px, -9px);\n",
              "  height: 36px;\n",
              "  width: 9px;\n",
              "}\n",
              "@media (prefers-color-scheme: light) {\n",
              "  .container {\n",
              "    background-color: #fafafa;\n",
              "    box-shadow: 0 0 0 1px #0000000f;\n",
              "  }\n",
              "  .headline-label {\n",
              "    color: #1f1f1f;\n",
              "  }\n",
              "  .chip {\n",
              "    background-color: #ffffff;\n",
              "    border-color: #d2d2d2;\n",
              "    color: #5e5e5e;\n",
              "    text-decoration: none;\n",
              "  }\n",
              "  .chip:hover {\n",
              "    background-color: #f2f2f2;\n",
              "  }\n",
              "  .chip:focus {\n",
              "    background-color: #f2f2f2;\n",
              "  }\n",
              "  .chip:active {\n",
              "    background-color: #d8d8d8;\n",
              "    border-color: #b6b6b6;\n",
              "  }\n",
              "  .logo-dark {\n",
              "    display: none;\n",
              "  }\n",
              "  .gradient {\n",
              "    background: linear-gradient(90deg, #fafafa 15%, #fafafa00 100%);\n",
              "  }\n",
              "}\n",
              "@media (prefers-color-scheme: dark) {\n",
              "  .container {\n",
              "    background-color: #1f1f1f;\n",
              "    box-shadow: 0 0 0 1px #ffffff26;\n",
              "  }\n",
              "  .headline-label {\n",
              "    color: #fff;\n",
              "  }\n",
              "  .chip {\n",
              "    background-color: #2c2c2c;\n",
              "    border-color: #3c4043;\n",
              "    color: #fff;\n",
              "    text-decoration: none;\n",
              "  }\n",
              "  .chip:hover {\n",
              "    background-color: #353536;\n",
              "  }\n",
              "  .chip:focus {\n",
              "    background-color: #353536;\n",
              "  }\n",
              "  .chip:active {\n",
              "    background-color: #464849;\n",
              "    border-color: #53575b;\n",
              "  }\n",
              "  .logo-light {\n",
              "    display: none;\n",
              "  }\n",
              "  .gradient {\n",
              "    background: linear-gradient(90deg, #1f1f1f 15%, #1f1f1f00 100%);\n",
              "  }\n",
              "}\n",
              "</style>\n",
              "<div class=\"container\">\n",
              "  <div class=\"headline\">\n",
              "    <svg class=\"logo-light\" width=\"18\" height=\"18\" viewBox=\"9 9 35 35\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n",
              "      <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M42.8622 27.0064C42.8622 25.7839 42.7525 24.6084 42.5487 23.4799H26.3109V30.1568H35.5897C35.1821 32.3041 33.9596 34.1222 32.1258 35.3448V39.6864H37.7213C40.9814 36.677 42.8622 32.2571 42.8622 27.0064V27.0064Z\" fill=\"#4285F4\"/>\n",
              "      <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M26.3109 43.8555C30.9659 43.8555 34.8687 42.3195 37.7213 39.6863L32.1258 35.3447C30.5898 36.3792 28.6306 37.0061 26.3109 37.0061C21.8282 37.0061 18.0195 33.9811 16.6559 29.906H10.9194V34.3573C13.7563 39.9841 19.5712 43.8555 26.3109 43.8555V43.8555Z\" fill=\"#34A853\"/>\n",
              "      <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M16.6559 29.8904C16.3111 28.8559 16.1074 27.7588 16.1074 26.6146C16.1074 25.4704 16.3111 24.3733 16.6559 23.3388V18.8875H10.9194C9.74388 21.2072 9.06992 23.8247 9.06992 26.6146C9.06992 29.4045 9.74388 32.022 10.9194 34.3417L15.3864 30.8621L16.6559 29.8904V29.8904Z\" fill=\"#FBBC05\"/>\n",
              "      <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M26.3109 16.2386C28.85 16.2386 31.107 17.1164 32.9095 18.8091L37.8466 13.8719C34.853 11.082 30.9659 9.3736 26.3109 9.3736C19.5712 9.3736 13.7563 13.245 10.9194 18.8875L16.6559 23.3388C18.0195 19.2636 21.8282 16.2386 26.3109 16.2386V16.2386Z\" fill=\"#EA4335\"/>\n",
              "    </svg>\n",
              "    <svg class=\"logo-dark\" width=\"18\" height=\"18\" viewBox=\"0 0 48 48\" xmlns=\"http://www.w3.org/2000/svg\">\n",
              "      <circle cx=\"24\" cy=\"23\" fill=\"#FFF\" r=\"22\"/>\n",
              "      <path d=\"M33.76 34.26c2.75-2.56 4.49-6.37 4.49-11.26 0-.89-.08-1.84-.29-3H24.01v5.99h8.03c-.4 2.02-1.5 3.56-3.07 4.56v.75l3.91 2.97h.88z\" fill=\"#4285F4\"/>\n",
              "      <path d=\"M15.58 25.77A8.845 8.845 0 0 0 24 31.86c1.92 0 3.62-.46 4.97-1.31l4.79 3.71C31.14 36.7 27.65 38 24 38c-5.93 0-11.01-3.4-13.45-8.36l.17-1.01 4.06-2.85h.8z\" fill=\"#34A853\"/>\n",
              "      <path d=\"M15.59 20.21a8.864 8.864 0 0 0 0 5.58l-5.03 3.86c-.98-2-1.53-4.25-1.53-6.64 0-2.39.55-4.64 1.53-6.64l1-.22 3.81 2.98.22 1.08z\" fill=\"#FBBC05\"/>\n",
              "      <path d=\"M24 14.14c2.11 0 4.02.75 5.52 1.98l4.36-4.36C31.22 9.43 27.81 8 24 8c-5.93 0-11.01 3.4-13.45 8.36l5.03 3.85A8.86 8.86 0 0 1 24 14.14z\" fill=\"#EA4335\"/>\n",
              "    </svg>\n",
              "    <div class=\"gradient-container\"><div class=\"gradient\"></div></div>\n",
              "  </div>\n",
              "  <div class=\"carousel\">\n",
              "    <a class=\"chip\" href=\"https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFUTcqlvB7Zrn9n3b5FSWS0NWG_udXDjOjFWwo4MIHMEqh3rwjPY-RksKhjCICyM39IDRxiL0o9KmDi6Kmx56wRSugGCBn8CKNu0gYdaMpRATB5_OHJOM76nBsqkXTdK-9mMg70RRZjG39Cc6mgXpGu-Jf04dYvck6bBaVPiOUnhCkEXfmAu6kStkPchPwb5iyNyDMussf3Eayze_Jv9cXzBQE=\">Brazil vs Argentina last match result</a>\n",
              "    <a class=\"chip\" href=\"https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQE0oSxQgZRY9DHrpitcilTgkQXG_SxGgaOmgyfkfbNsneYXpcMyUEL2MqFdtF41o_9lZCB0BiZIagRKUqiIRAHtl9g0wJXBuDCDcJPZvG_IFy1R7jTtGmK0ADQg6oshkpAfPK7qUWwFJPRIu46TqGp7UooZXxVEtFdHFpEBYDZmjBO1Vj711bs9bZZM2o0KVkW7-Ldtf_JClFl9zJwzNM2VdSWCT861jycKm4SfU830ZsFFXaT8\">latest Brazil vs. Argentina soccer match date and score</a>\n",
              "  </div>\n",
              "</div>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "prompt=\"When the latest Brazil vs. Argentina soccer match happened and what was the final score?\"\n",
        "\n",
        "tools = [\n",
        "   {'google_search': {}}\n",
        "]\n",
        "\n",
        "await run(prompt, tools=tools, modality=\"TEXT\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "HM9y5rwfqKfY"
      },
      "source": [
        "## Multi-tool\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "qrxAQjYA6vQX"
      },
      "source": [
        "The biggest difference with the new API however is that you're no longer limited to using 1-tool per request. Try combining those tasks from the previous sections:"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": 53,
      "metadata": {
        "id": "QmB_4XPOslyA"
      },
      "outputs": [
        {
          "data": {
            "text/markdown": "  Hey, I need you to do three things for me.\n\n  1. Then compute the largest prime plaindrome under 100000.\n  2. Then use google search to lookup unformation about the largest earthquake in california the week of Dec 5 2024?\n  3. Turn on the lights\n\n  Thanks!\n  ",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` python\ndef is_palindrome(n):\n    return str(n) == str(n)[::-1]\n\ndef is_prime(n):\n    if n < 2:\n        return False\n    for i in range(2, int(n**0.5) + 1):\n        if n % i == 0:\n            return False\n    return True\n\nlargest_prime_palindrome = 0\nfor i in range(99999, 1, -1):\n    if is_palindrome(i) and is_prime(i):\n        largest_prime_palindrome = i\n        break\n\nprint(f\"The largest prime palindrome under 100000 is: {largest_prime_palindrome}\")\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` \nThe largest prime palindrome under 100000 is: 98689\n\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` python\nconcise_search(\"largest earthquake in california the week of Dec 5 2024\")\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` \nLooking up information on Google Search.\n\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "``` python\ndefault_api.turn_on_the_lights()\n```",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "-------------------------------",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/html": [
              "<style>\n",
              ".container {\n",
              "  align-items: center;\n",
              "  border-radius: 8px;\n",
              "  display: flex;\n",
              "  font-family: Google Sans, Roboto, sans-serif;\n",
              "  font-size: 14px;\n",
              "  line-height: 20px;\n",
              "  padding: 8px 12px;\n",
              "}\n",
              ".chip {\n",
              "  display: inline-block;\n",
              "  border: solid 1px;\n",
              "  border-radius: 16px;\n",
              "  min-width: 14px;\n",
              "  padding: 5px 16px;\n",
              "  text-align: center;\n",
              "  user-select: none;\n",
              "  margin: 0 8px;\n",
              "  -webkit-tap-highlight-color: transparent;\n",
              "}\n",
              ".carousel {\n",
              "  overflow: auto;\n",
              "  scrollbar-width: none;\n",
              "  white-space: nowrap;\n",
              "  margin-right: -12px;\n",
              "}\n",
              ".headline {\n",
              "  display: flex;\n",
              "  margin-right: 4px;\n",
              "}\n",
              ".gradient-container {\n",
              "  position: relative;\n",
              "}\n",
              ".gradient {\n",
              "  position: absolute;\n",
              "  transform: translate(3px, -9px);\n",
              "  height: 36px;\n",
              "  width: 9px;\n",
              "}\n",
              "@media (prefers-color-scheme: light) {\n",
              "  .container {\n",
              "    background-color: #fafafa;\n",
              "    box-shadow: 0 0 0 1px #0000000f;\n",
              "  }\n",
              "  .headline-label {\n",
              "    color: #1f1f1f;\n",
              "  }\n",
              "  .chip {\n",
              "    background-color: #ffffff;\n",
              "    border-color: #d2d2d2;\n",
              "    color: #5e5e5e;\n",
              "    text-decoration: none;\n",
              "  }\n",
              "  .chip:hover {\n",
              "    background-color: #f2f2f2;\n",
              "  }\n",
              "  .chip:focus {\n",
              "    background-color: #f2f2f2;\n",
              "  }\n",
              "  .chip:active {\n",
              "    background-color: #d8d8d8;\n",
              "    border-color: #b6b6b6;\n",
              "  }\n",
              "  .logo-dark {\n",
              "    display: none;\n",
              "  }\n",
              "  .gradient {\n",
              "    background: linear-gradient(90deg, #fafafa 15%, #fafafa00 100%);\n",
              "  }\n",
              "}\n",
              "@media (prefers-color-scheme: dark) {\n",
              "  .container {\n",
              "    background-color: #1f1f1f;\n",
              "    box-shadow: 0 0 0 1px #ffffff26;\n",
              "  }\n",
              "  .headline-label {\n",
              "    color: #fff;\n",
              "  }\n",
              "  .chip {\n",
              "    background-color: #2c2c2c;\n",
              "    border-color: #3c4043;\n",
              "    color: #fff;\n",
              "    text-decoration: none;\n",
              "  }\n",
              "  .chip:hover {\n",
              "    background-color: #353536;\n",
              "  }\n",
              "  .chip:focus {\n",
              "    background-color: #353536;\n",
              "  }\n",
              "  .chip:active {\n",
              "    background-color: #464849;\n",
              "    border-color: #53575b;\n",
              "  }\n",
              "  .logo-light {\n",
              "    display: none;\n",
              "  }\n",
              "  .gradient {\n",
              "    background: linear-gradient(90deg, #1f1f1f 15%, #1f1f1f00 100%);\n",
              "  }\n",
              "}\n",
              "</style>\n",
              "<div class=\"container\">\n",
              "  <div class=\"headline\">\n",
              "    <svg class=\"logo-light\" width=\"18\" height=\"18\" viewBox=\"9 9 35 35\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\">\n",
              "      <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M42.8622 27.0064C42.8622 25.7839 42.7525 24.6084 42.5487 23.4799H26.3109V30.1568H35.5897C35.1821 32.3041 33.9596 34.1222 32.1258 35.3448V39.6864H37.7213C40.9814 36.677 42.8622 32.2571 42.8622 27.0064V27.0064Z\" fill=\"#4285F4\"/>\n",
              "      <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M26.3109 43.8555C30.9659 43.8555 34.8687 42.3195 37.7213 39.6863L32.1258 35.3447C30.5898 36.3792 28.6306 37.0061 26.3109 37.0061C21.8282 37.0061 18.0195 33.9811 16.6559 29.906H10.9194V34.3573C13.7563 39.9841 19.5712 43.8555 26.3109 43.8555V43.8555Z\" fill=\"#34A853\"/>\n",
              "      <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M16.6559 29.8904C16.3111 28.8559 16.1074 27.7588 16.1074 26.6146C16.1074 25.4704 16.3111 24.3733 16.6559 23.3388V18.8875H10.9194C9.74388 21.2072 9.06992 23.8247 9.06992 26.6146C9.06992 29.4045 9.74388 32.022 10.9194 34.3417L15.3864 30.8621L16.6559 29.8904V29.8904Z\" fill=\"#FBBC05\"/>\n",
              "      <path fill-rule=\"evenodd\" clip-rule=\"evenodd\" d=\"M26.3109 16.2386C28.85 16.2386 31.107 17.1164 32.9095 18.8091L37.8466 13.8719C34.853 11.082 30.9659 9.3736 26.3109 9.3736C19.5712 9.3736 13.7563 13.245 10.9194 18.8875L16.6559 23.3388C18.0195 19.2636 21.8282 16.2386 26.3109 16.2386V16.2386Z\" fill=\"#EA4335\"/>\n",
              "    </svg>\n",
              "    <svg class=\"logo-dark\" width=\"18\" height=\"18\" viewBox=\"0 0 48 48\" xmlns=\"http://www.w3.org/2000/svg\">\n",
              "      <circle cx=\"24\" cy=\"23\" fill=\"#FFF\" r=\"22\"/>\n",
              "      <path d=\"M33.76 34.26c2.75-2.56 4.49-6.37 4.49-11.26 0-.89-.08-1.84-.29-3H24.01v5.99h8.03c-.4 2.02-1.5 3.56-3.07 4.56v.75l3.91 2.97h.88z\" fill=\"#4285F4\"/>\n",
              "      <path d=\"M15.58 25.77A8.845 8.845 0 0 0 24 31.86c1.92 0 3.62-.46 4.97-1.31l4.79 3.71C31.14 36.7 27.65 38 24 38c-5.93 0-11.01-3.4-13.45-8.36l.17-1.01 4.06-2.85h.8z\" fill=\"#34A853\"/>\n",
              "      <path d=\"M15.59 20.21a8.864 8.864 0 0 0 0 5.58l-5.03 3.86c-.98-2-1.53-4.25-1.53-6.64 0-2.39.55-4.64 1.53-6.64l1-.22 3.81 2.98.22 1.08z\" fill=\"#FBBC05\"/>\n",
              "      <path d=\"M24 14.14c2.11 0 4.02.75 5.52 1.98l4.36-4.36C31.22 9.43 27.81 8 24 8c-5.93 0-11.01 3.4-13.45 8.36l5.03 3.85A8.86 8.86 0 0 1 24 14.14z\" fill=\"#EA4335\"/>\n",
              "    </svg>\n",
              "    <div class=\"gradient-container\"><div class=\"gradient\"></div></div>\n",
              "  </div>\n",
              "  <div class=\"carousel\">\n",
              "    <a class=\"chip\" href=\"https://vertexaisearch.cloud.google.com/grounding-api-redirect/AUZIYQFqD908tLjR0Dj9fGhhodiqm4PKICStO17eoEUSE1Oh6tSP1duKUk5X5G5Lg-EEGdTiX0IfHiBnS-FSOagA1H8ivgIuUdzcef25YzrLUs0dN8wIUkGG4rg7h5LkHLY4FjahLYzEqD4tFmE-OIzxEfx0hTJLfIzBJBv1ASSwJ11QLWH78G22NFttpsCIDcSzOFzSEeAin4H8qt9WNFzVIsH7f7RDQygfFxWGx_uXuMTMwo_5z6fb5g==\">largest earthquake in california the week of Dec 5 2024</a>\n",
              "  </div>\n",
              "</div>\n"
            ],
            "text/plain": [
              "<IPython.core.display.HTML object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "name": "stdout",
          "output_type": "stream",
          "text": [
            "Tool call:\n",
            ">>>  [FunctionResponse(\n",
            "  id='function-call-6911647360850859452',\n",
            "  name='turn_on_the_lights',\n",
            "  response={\n",
            "    'result': 'ok'\n",
            "  }\n",
            ")]\n"
          ]
        },
        {
          "data": {
            "text/markdown": "I'",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": "ve completed all three of your requests:\n\n1.  The largest prime palindrome under",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " 100000 is **98689**.\n2.  Based on the search results, a **magnitude 7.0 earthquake** struck offshore of Cape Mendocino, Northern California, on **December 5,",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        },
        {
          "data": {
            "text/markdown": " 2024**. This appears to be the largest earthquake in California during that week.\n3.  I have turned on the lights.",
            "text/plain": [
              "<IPython.core.display.Markdown object>"
            ]
          },
          "metadata": {},
          "output_type": "display_data"
        }
      ],
      "source": [
        "prompt = \"\"\"\\\n",
        "  Hey, I need you to do three things for me.\n",
        "\n",
        "  1. Then compute the largest prime plaindrome under 100000.\n",
        "  2. Then use google search to lookup unformation about the largest earthquake in california the week of Dec 5 2024?\n",
        "  3. Turn on the lights\n",
        "\n",
        "  Thanks!\n",
        "  \"\"\"\n",
        "\n",
        "tools = [\n",
        "    {'google_search': {}},\n",
        "    {'code_execution': {}},\n",
        "    {'function_declarations': [turn_on_the_lights, turn_off_the_lights]}\n",
        "]\n",
        "\n",
        "await run(prompt, tools=tools, modality=\"TEXT\")"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {
        "id": "Y0OhM95KkMzl"
      },
      "source": [
        "## Next Steps\n",
        "\n",
        "- For more information about the SDK see the [SDK docs](https://googleapis.github.io/python-genai/)\n",
        "- This tutorial uses the high level SDK, if you're interested in the lower-level details, try the [Websocket version of this tutorial](../quickstarts/websockets/Get_started_LiveAPI_tools.ipynb)\n",
        "- This tutorial only covers _basic_ usage of these tools for deeper (and more fun) example see the [Search tool tutorial](./Search_Grounding.ipynb)\n",
        "\n",
        "Or check the other Gemini 2.5 capabilities from the [Cookbook](../gemini-2/), in particular this other [multi-tool](../examples/LiveAPI_plotting_and_mapping.ipynb) example and the one about Gemini [spatial capabilities](../quickstarts/Spatial_understanding.ipynb)."
      ]
    }
  ],
  "metadata": {
    "colab": {
      "name": "Get_started_LiveAPI_tools.ipynb",
      "toc_visible": true
    },
    "kernelspec": {
      "display_name": "Python 3",
      "name": "python3"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}
